package com.vectz.mgt.action;

import java.io.IOException;
import java.util.ArrayList;

import javax.persistence.Embedded;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.Lob;
import javax.persistence.ManyToOne;

import com.vectz.mgt.model.Entity;
import com.vectz.mgt.model.EntityOverview;
import com.vectz.mgt.util.Log;
import com.vectz.mgt.util.Util;

/**
 * @author ai-t.vn
 * 
 */
public class ModelCodegenAction {
	private ArrayList<Entity> listField = null;
	private EntityOverview table = null;
	private String outputFolder = "";

	public ModelCodegenAction(ArrayList<Entity> listField,
			EntityOverview table, String outputFolder) throws Exception {
		this.listField = listField;
		this.table = table;
		this.outputFolder = outputFolder;
		genernateModelFile();
	}

	/*
	 * Generate jsf file (add new entity form)
	 */
	public void genernateModelFile()  throws Exception {

			StringBuffer modelContent = new StringBuffer();

			String tmplFieldNameContent = Util.readTextFileContent(Util
					.getTmplPath("model", "Entity-FieldName.txt"));
			String tmplFieldMethodContent = Util.readTextFileContent(Util
					.getTmplPath("model", "Entity-FieldMethod.txt"));
			String tmplFileHeaderContent = Util.readTextFileContent(Util
					.getTmplPath("model", "Entity-FileHeader.txt"));

			// add content path
			modelContent.append(genernateHeaderFile(table,
					tmplFileHeaderContent));
			modelContent.append(genernateFieldName(listField,
					tmplFieldNameContent));
			modelContent.append(genernateFieldMethod(listField,
					tmplFieldMethodContent));
			// append block end of class
			modelContent.append("}");
			String fileLocation = new StringBuffer().append(outputFolder)
					.append(System.getProperty("file.separator")).append("src")
					.append(System.getProperty("file.separator")).append(
							"model").append(
							System.getProperty("file.separator")).append(
							table.getName()).append(".java").toString();
			Util.writeJsfFile(fileLocation, modelContent.toString());
			Log.log("Finish generate model file to:" + fileLocation);

	}

	/*
	 * Generate header file
	 */
	public String genernateHeaderFile(EntityOverview dataTable,
			String tmpContent) {
		if (Util.isEmpty(tmpContent))
			return "";
		tmpContent = tmpContent.replaceAll("xxxxPackageName", dataTable
				.getPackageName());
		tmpContent = tmpContent
				.replaceAll("xxxxClassName", dataTable.getName());

		// tmpContent = tmpContent.replaceAll("xxxxEntityListeners", new
		// StringBuilder().
		// append("@EntityListeners(").
		// append(dataTable.getEntityListenerClass()).
		// append(")").toString());

		return tmpContent;
	}

	/*
	 * Generate list field name
	 */
	public String genernateFieldName(ArrayList<Entity> listField,
			String tmplContent) {
		StringBuffer content = new StringBuffer();

		if (listField == null)
			return "";
		Entity field = null;
		for (int i = 0; i < listField.size(); i++) {
			field = (Entity) listField.get(i);
			String strAnnotation = "";
			if (field != null) {
				// replace field name
				String tmp = tmplContent.replaceAll("xxxxFieldName", Util.lowerCaseFirstChar(field
						.getName()));
				tmp = tmp
						.replaceAll("xxxxJapaneseName", field.getLogicalName());
				tmp = tmp.replaceAll("xxxxFieldDescription", field
						.getScreenName());
				/* if inputType is selectManyCheckbox and inputDataType = java.lang.String
				 * then replace xxxxFieldType to java.lang.String[]
				 * and convert to String data type
				 * Modify by anhdv 2008-10-29
				 */
				if(field.getInputType()!= null 
						&& Util.dbTypeToJavaType(field.getInputDataType()).equalsIgnoreCase("java.lang.String")
						&& field.getInputType().equalsIgnoreCase("selectManyCheckbox")){
					tmp = tmp.replaceAll("xxxxFieldType", "java.lang.String[]");
					strAnnotation = "\t@Enumerated(EnumType.STRING)\n";
				}// get @Embedded annotation when field is VECDATETIME
				// Modify by anhdv 2008-10-20
				else if(field.getInputDataType()!= null 
						&& field.getInputDataType().equalsIgnoreCase("VECDATETIME")){
					// replace field type
					tmp = tmp.replaceAll("xxxxFieldType", Util
							.dbTypeToJavaType(field.getInputDataType()));
					strAnnotation = "\t@Embedded\n";
				} // get @Lob when field is byte[]
				else if(field.getInputDataType()!= null 
				&& Util.dbTypeToJavaType(field.getInputDataType()).equalsIgnoreCase("byte[]")){
					// replace field type
					tmp = tmp.replaceAll("xxxxFieldType", Util
							.dbTypeToJavaType(field.getInputDataType()));
					strAnnotation = "\t@Lob\n";
			   }// get @ManyToOne annotation when field is FK and set dataType
				else if (field.getKeyType().equalsIgnoreCase("FK")) {
					// replace field type
					tmp = tmp.replaceAll("xxxxFieldType", Util.upperCaseFirstChar(field.getKeyReference()));
					strAnnotation = "\t@ManyToOne\n";
				} else {
					// replace field type
					tmp = tmp.replaceAll("xxxxFieldType", Util
							.dbTypeToJavaType(field.getInputDataType()));
					// get @Id annotation when field is PK
					if (field.getKeyType().equalsIgnoreCase("PK")){
						strAnnotation = "\t@Id\n";
						//if PK field not add by manual then set to auto generate
						if (field.getDisplay()!= null && !field.getDisplay().equalsIgnoreCase("show"))
							strAnnotation += "\t@GeneratedValue\n";
					}
				}

				// get @NotNull annotation
				if (field.getRequired().equalsIgnoreCase("true"))
					strAnnotation += "\t@NotNull\n";
				// get @Length(max) annotation
				if (!Util.isEmpty(field.getInputLength()))
					strAnnotation += new StringBuilder().append(
							"\t@Column(length=").append(field.getInputLength())
							.append(")\n").toString();
				// replace /n in the end of annotation
				if (!Util.isEmpty(strAnnotation))
					strAnnotation = strAnnotation.substring(0, strAnnotation
							.length() - 1);
				// replace all annotation
				tmp = tmp.replaceAll("xxxxFieldAnnotation", strAnnotation);
				content.append(tmp);
			}
		}

		return content.toString();
	}

	/*
	 * Generate list field method
	 */
	public String genernateFieldMethod(ArrayList<Entity> listField,
			String tmplContent) {
		StringBuffer content = new StringBuffer();
		if (listField == null)
			return "";
		Entity field = null;
		for (int i = 0; i < listField.size(); i++) {
			field = (Entity) listField.get(i);
			if (field != null) {
				String tmp = "";
				/* if inputType is selectManyCheckbox and inputtype=java.lang.String
				 *then replace xxxxFieldType to java.lang.String[]
				 * Modify by anhdv 2008-10-29
				 */
				if(field.getInputType()!= null 
						&& Util.dbTypeToJavaType(field.getInputDataType()).equalsIgnoreCase("java.lang.String")
						&& field.getInputType().equalsIgnoreCase("selectManyCheckbox")){
					tmp = tmplContent.replaceAll("xxxxFieldType","java.lang.String[]");
				}
				// get @ManyToOne annotation when field is FK and set dataType
				else if (field.getKeyType().equalsIgnoreCase("FK")) {
					// replace field type
					tmp = tmplContent.replaceAll("xxxxFieldType", Util.upperCaseFirstChar(field.getKeyReference()));
				}else{
					tmp = tmplContent.replaceAll("xxxxFieldType", Util
						.dbTypeToJavaType(field.getInputDataType()));
				}
				String firstUpFieldName = Util.upperCaseFirstChar(field
						.getName());
				tmp = tmp.replaceAll("getXxxxFieldName", (new StringBuilder())
						.append("get").append(firstUpFieldName).toString());
				tmp = tmp.replaceAll("xxxxFieldName", Util.lowerCaseFirstChar(field.getName()));
				tmp = tmp.replaceAll("xxxxFieldDescription", field
						.getScreenName());
				// check if data type is java.lang.Boolean
//				if (Util.dbTypeToJavaType(field.getInputDataType()).indexOf(
//						"Boolean") != -1)
//					tmp = tmp.replaceAll("setXxxxFieldName",
//							(new StringBuilder()).append("is").append(
//									firstUpFieldName).toString());
//				else
					tmp = tmp.replaceAll("setXxxxFieldName",
							(new StringBuilder()).append("set").append(
									firstUpFieldName).toString());
				content.append(tmp);
			}
		}

		return content.toString();
	}
}
